home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / HOSTABLE.C < prev    next >
C/C++ Source or Header  |  1991-11-21  |  22KB  |  572 lines

  1. /*
  2.    h o s t a b l e . c
  3.  
  4.    Remote host table routines for UUPC/extended
  5.  
  6.    Copyright (C) 1989, 1990 by Andrew H. Derbyshire
  7.  
  8.    See file README.SCR for restrictions on re-distribution.
  9.  
  10.    History:
  11.  
  12.       18 Mar 1990 Create hostable.c from router.c                    ahd
  13.                   Move code to generate localdomain to here          ahd
  14.       22 Apr 90   Perform check for full host name before examining
  15.                   name without domain.                               ahd
  16.       29 Jul 90   Only load host table based on first six characters
  17.                   of host name.                                      ahd
  18.  */
  19.  
  20. #include <ctype.h>
  21. #include <limits.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <sys/types.h>
  26.  
  27. #include "lib.h"
  28. #include "hlib.h"
  29. #include "hostable.h"
  30. #include "security.h"
  31.  
  32. currentfile();
  33.  
  34. static struct HostTable *hosts = NULL;
  35.  
  36. static size_t  HostElements = 0;
  37.  
  38. static size_t loadhost( void );
  39.  
  40. static int hostcmp( const void *a , const void *b );
  41.  
  42. static size_t localdomainl;   /* Length of localdomain               */
  43.  
  44. /*--------------------------------------------------------------------*/
  45. /*    c h e c k n a m e                                               */
  46. /*                                                                    */
  47. /*    Perform a search for a single host name                         */
  48. /*                                                                    */
  49. /*    Rewritten for release 1.10a.  The old release had               */
  50. /*    most of the same logic, but nested it inside the search         */
  51. /*    loop; adding new cases (specifically, the wildcard domain       */
  52. /*    search) was difficult.  This version is slower because it       */
  53. /*    makes multiple passes through the host table, but this          */
  54. /*    isn't really performance code for a small (under 100 hosts)     */
  55. /*    table.                                 ahd 26 April 1991        */
  56. /*                                                                    */
  57. /*    Note because we save the arguments and use a static variable    */
  58. /*    to save the result of searches, this function is not            */
  59. /*    recursive!                                                      */
  60. /*--------------------------------------------------------------------*/
  61.  
  62. struct HostTable *checkname(const char *name)
  63. {
  64.    char  hostname[MAXADDR];   /* Local copy of name to process       */
  65.    char *period;              /* Pointer "." in hostname             */
  66.    size_t namel;              /* Length of the name input            */
  67.    size_t column;             /* Length of the name input            */
  68.  
  69.    static char savename[MAXADDR] = "";
  70.                               /* Saved copy of name to make function
  71.                                  reducible                           */
  72.    static struct HostTable *hostz;
  73.  
  74. /*--------------------------------------------------------------------*/
  75. /*                       Validate the argument                        */
  76. /*--------------------------------------------------------------------*/
  77.  
  78.    if ((name == NULL) || ((namel = strlen(name)) == 0))
  79.    {
  80.       printmsg(0,"checkname: Invalid (missing) hostname passed");
  81.       panic();
  82.    }
  83.  
  84. /*--------------------------------------------------------------------*/
  85. /*    If same argument as last time, return same result; otherwise    */
  86. /*    save input for next pass                                        */
  87. /*--------------------------------------------------------------------*/
  88.  
  89.    if (equal(name, savename))
  90.       return hostz;
  91.    strcpy( savename, name);   /* Save for next pass                  */
  92.  
  93. /*--------------------------------------------------------------------*/
  94. /*                      Search for the full name                      */
  95. /*--------------------------------------------------------------------*/
  96.  
  97.    if ((hostz = searchname(name, MAXADDR)) != BADHOST)
  98.       return hostz;
  99.  
  100. /*--------------------------------------------------------------------*/
  101. /*    If the name already has the local domain attached, search for   */
  102. /*    the host name without the domain.                               */
  103. /*--------------------------------------------------------------------*/
  104.  
  105.    column = namel - localdomainl;
  106.    if ((namel > localdomainl) && equal(localdomain, &name[column]) &&
  107.        (name[ column - 1] == '.'))
  108.    {
  109.       if ((hostz = searchname(name,column-1 )) != BADHOST)
  110.          return hostz;
  111.    } /* if */
  112.  
  113. /*--------------------------------------------------------------------*/
  114. /*              Search for the name in the local domain               */
  115. /*--------------------------------------------------------------------*/
  116.  
  117.    if ((namel + localdomainl + 2) < MAXADDR)
  118.    {
  119.       sprintf(hostname,"%s.%s",name,localdomain);
  120.       if ((hostz = searchname(hostname, MAXADDR)) != BADHOST)
  121.          return hostz;
  122.    } /* if */
  123.  
  124. /*--------------------------------------------------------------------*/
  125. /*    If a simple name and not found, return search for truncated     */
  126. /*    UNIX name.                                                      */
  127. /*--------------------------------------------------------------------*/
  128.  
  129.    if ( strchr(name,'.') == NULL )
  130.       return checkreal( name );
  131.  
  132. /*--------------------------------------------------------------------*/
  133. /*               Perform a wildcard domain name search                */
  134. /*--------------------------------------------------------------------*/
  135.  
  136.    period = (char *) name;    /* Begin at front of name              */
  137.    while( period != NULL )
  138.    {
  139.       sprintf( hostname,(*period == '.') ? "*%s" : "*.%s",period);
  140.                               /* We add the missing period for the
  141.                                  first pass through the loop         */
  142.       if ((hostz = searchname(hostname, MAXADDR)) != BADHOST)
  143.          return hostz;
  144.       period = strchr(++period,'.');   /* Not found, search for next
  145.                                           higher domain              */
  146.    }
  147.  
  148. /*--------------------------------------------------------------------*/
  149. /*         We didn't find the host.  Return failure to caller         */
  150. /*--------------------------------------------------------------------*/
  151.  
  152.    return BADHOST;
  153.  
  154. }  /* checkname */
  155.  
  156. /*--------------------------------------------------------------------*/
  157. /*    c h e c k r e a l                                               */
  158. /*                                                                    */
  159. /*    Perform a search for a real (connected) simple host name        */
  160. /*--------------------------------------------------------------------*/
  161.  
  162. struct HostTable *checkreal(const char *name)
  163. {
  164.    size_t  namel = max( strlen(name), HOSTLEN);
  165.    struct HostTable *hostz = searchname( name, namel );
  166.  
  167. /*--------------------------------------------------------------------*/
  168. /*             If we didn't find the host, return failure             */
  169. /*--------------------------------------------------------------------*/
  170.  
  171.    if ((hostz == BADHOST) || (hostz->hstatus >= nocall))
  172.       return hostz;           /* Return raw information              */
  173.    else
  174.       return BADHOST;         /* Not a real host, invalid for our
  175.                                  purposes                            */
  176.  
  177. } /* searchreal */
  178.  
  179. /*--------------------------------------------------------------------*/
  180. /*    s e a r c h n a m e                                             */
  181. /*                                                                    */
  182. /*    Look up a system name in our systems (L.sys) file.              */
  183. /*    Only the first 7 characters of a system name is significant.    */
  184. /*--------------------------------------------------------------------*/
  185.  
  186. struct HostTable *searchname(const char *name, const size_t namel)
  187. {
  188.    int   lower;
  189.    int   upper;
  190.  
  191.  /*------------------------------------------------------------------*/
  192.  /*             Initialize the host name table if needed             */
  193.  /*------------------------------------------------------------------*/
  194.  
  195.    if (HostElements == 0)           /* host table initialized yet?   */
  196.       HostElements = loadhost();        /* No --> load it            */
  197.  
  198.    lower = 0;
  199.    upper = HostElements - 1;
  200.    while ( lower <= upper )
  201.    {
  202.       int midpoint = (lower + upper) / 2;
  203.       int hit;
  204.  
  205. /*--------------------------------------------------------------------*/
  206. /*    Compare for up to the specified length of the host name, but    */
  207. /*    never less than the length of the item we are comparing it      */
  208. /*    to.  In other words, the search key can be shorter than the     */
  209. /*    table entry for a simple host name.                             */
  210. /*                                                                    */
  211. /*    This mostly affects simple host names, as domain names          */
  212. /*    have a Very Large Number (VLN) passed into to insure we         */
  213. /*    compare the entire length of the name.                          */
  214. /*--------------------------------------------------------------------*/
  215.  
  216.       hit = strnicmp(name,hosts[midpoint].hostname,namel);
  217.       if (hit > 0)
  218.          lower = midpoint + 1;
  219.       else if ((hit < 0) || (strlen(hosts[midpoint].hostname) > namel))
  220.          upper = midpoint - 1;
  221.       else {
  222.             printmsg(8,"searchname: Looking for \"%s\" of length %d,\
  223.  found \"%s\" via \"%s\"",
  224.             name, namel, hosts[midpoint].hostname, hosts[midpoint].via);
  225.          return &hosts[midpoint];
  226.       }
  227.    }
  228.  
  229. /*--------------------------------------------------------------------*/
  230. /*         We didn't find the host.  Return failure to caller         */
  231. /*--------------------------------------------------------------------*/
  232.  
  233.    printmsg(8,"searchname: Looking for \"%s\", did not find it",
  234.             name);
  235.    return BADHOST;
  236.  
  237. }  /* searchname */
  238.  
  239.  
  240. /*--------------------------------------------------------------------*/
  241. /*    n e x t h o s t                                                 */
  242. /*                                                                    */
  243. /*    Returns next host in table with requested attribute             */
  244. /*--------------------------------------------------------------------*/
  245.  
  246. struct HostTable *nexthost( const boolean start , const hostatus status )
  247. {
  248.    static size_t current = 0;
  249.  
  250.    if (HostElements == 0)     /* host table initialized yet?         */
  251.       HostElements = loadhost(); /* No --> load it                   */
  252.  
  253.    if (start)
  254.       current = 0;
  255.    else
  256.       current ++;
  257.  
  258.    while ( current < HostElements )
  259.    {
  260.       if (hosts[current].hstatus > status)
  261.          return &hosts[current];
  262.       else
  263.          current++;
  264.    }
  265.  
  266.    return BADHOST;
  267.  
  268. }  /* nexthost */
  269.  
  270.  
  271. /*
  272.       i n i t h o s t
  273.  
  274.       Intializes a host table entry for for loadhost
  275.  */
  276.  
  277. struct HostTable *inithost(char *name)
  278. {
  279.  
  280.    size_t hit = HostElements;
  281.    size_t element = 0;
  282.    static size_t max_elements = 32; /* This is automatically
  283.                                        raised if we run out of room  */
  284.  
  285.    if (hosts == NULL)
  286.    {
  287.       hosts = calloc(max_elements, sizeof(*hosts));
  288.       printmsg(5,"inithost: Allocated room for %d host entries",
  289.                max_elements);
  290.    }
  291.    else if ( max_elements == HostElements )
  292.    {
  293.       max_elements = max_elements * 2;
  294.       hosts = realloc(hosts , max_elements * sizeof(*hosts));
  295.       printmsg(5,"inithost: reallocated room for %d host entries",
  296.                max_elements);
  297.    }
  298.    checkref(hosts);
  299.  
  300. /*--------------------------------------------------------------------*/
  301. /*    Add the host to the table.  Note that we must add the host      */
  302. /*    to the table ourselves (rather than use lsearch) because we     */
  303. /*    must make a copy of the string; the *token we use for the       */
  304. /*    search is in the middle of our I/O buffer!                      */
  305. /*--------------------------------------------------------------------*/
  306.  
  307.    while ( element < hit )
  308.    {
  309.       if (equali( hosts[element].hostname , name ))
  310.          hit = element;
  311.       else
  312.          element++;
  313.    }
  314.  
  315.    if (hit == HostElements)
  316.    {
  317.       hosts[hit].via = hosts[hit].hostname = strdup(name);
  318.       hosts[hit].called   = FALSE;
  319.       hosts[hit].hstats   = NULL;
  320.       hosts[hit].hstatus  = phantom;
  321.       hosts[hit].hsecure  = NULL;
  322.       HostElements ++ ;
  323.    } /* if */
  324.    return &hosts[hit];
  325. } /* inithost */
  326.  
  327.  
  328. /*--------------------------------------------------------------------*/
  329. /*    l o a d h o s t                                                 */
  330. /*                                                                    */
  331. /*    Initializes table of known host names for checkname             */
  332. /*--------------------------------------------------------------------*/
  333.  
  334. static size_t loadhost()
  335. {
  336.    FILE *ff;
  337.    char buf[BUFSIZ];
  338.    char *token;
  339.    char s_systems[FILENAME_MAX]; /* full-name of systems file        */
  340.    size_t hit;
  341.    boolean hidden;            /* Hidden via "fromdomain" keyword     */
  342.    struct HostTable *hostp;
  343.  
  344. /*--------------------------------------------------------------------*/
  345. /*                  Load the local host information                   */
  346. /*--------------------------------------------------------------------*/
  347.  
  348.    hostp = inithost(nodename);
  349.    hostp->hstatus = localhost;
  350.  
  351. /*--------------------------------------------------------------------*/
  352. /*    If the user is using a fromdomain entry, our true domain        */
  353. /*    name must be unique; load it first to insure this.              */
  354. /*--------------------------------------------------------------------*/
  355.  
  356.    hidden = fdomain != NULL;
  357.    if (hidden)                /* If using fromdomain ...             */
  358.    {                          /* domain is forced to be true domain  */
  359.       hostp = inithost(domain);
  360.       if (hostp->hstatus == phantom)      /* Uninitilized?        */
  361.       {
  362.          hostp->hstatus = aliasof;
  363.          hostp->via = nodename;
  364.       }
  365.    }  /* if (hidden) */
  366.  
  367. /*--------------------------------------------------------------------*/
  368. /*    If we allow anonymous UUCP, load the dummy host we use for      */
  369. /*    connections to such hosts                                       */
  370. /*--------------------------------------------------------------------*/
  371.  
  372.    if ( anonymous != NULL )
  373.    {
  374.       hostp = inithost( ANONYMOUS_HOST );
  375.       hostp->hstatus = localhost;
  376.       hostp->hstatus = nocall;
  377.       hostp->hstats  = malloc( sizeof *(hostp->hstats) );
  378.       checkref( hostp->hstats );
  379.       memset( hostp->hstats, 0, sizeof *(hostp->hstats) );
  380.    } /* if */
  381.  
  382. /*--------------------------------------------------------------------*/
  383. /*                  Load names from the systems file                  */
  384. /*--------------------------------------------------------------------*/
  385.  
  386.    mkfilename(s_systems, confdir, SYSTEMS);
  387.  
  388.    ff = FOPEN(s_systems, "r", TEXT);
  389.    if (ff == NULL)
  390.    {
  391.       printerr(s_systems);
  392.       panic();
  393.    }
  394.  
  395.    while (! feof(ff)) {
  396.       if (fgets(buf,BUFSIZ,ff) == NULL)   /* Try to read a line      */
  397.          break;                  /* Exit if end of file              */
  398.       token = strtok(buf,WHITESPACE);
  399.       if (token == NULL)         /* Any data?                        */
  400.          continue;               /* No --> read another line         */
  401.       if (token[0] == '#')
  402.          continue;                  /* Line is a comment; loop again */
  403.       hostp = inithost(token);
  404.  
  405.       if (hostp->hstatus == phantom)
  406.       {
  407.          hostp->hstatus = nocall;
  408.          hostp->hstats  = malloc( sizeof *(hostp->hstats) );
  409.          checkref( hostp->hstats );
  410.          memset( hostp->hstats, 0, sizeof *(hostp->hstats) );
  411.       }
  412.       else
  413.          printmsg(2,"loadhost: Duplicate entry in %s for \"%s\" ignored",
  414.                s_systems,
  415.                hostp->hostname);
  416.    } /* while */
  417.  
  418.    fclose(ff);
  419.  
  420. /*--------------------------------------------------------------------*/
  421. /*               Now the load the routing file, if any.               */
  422. /*--------------------------------------------------------------------*/
  423.  
  424.    mkfilename(s_systems, confdir, PATHS);
  425.  
  426.    if ((ff = FOPEN(s_systems, "r", TEXT)) != NULL)
  427.    {
  428.  
  429.       while (! feof(ff)) {
  430.          if (fgets(buf,BUFSIZ,ff) == NULL)   /* Try to read a line      */
  431.             break;                  /* Exit if end of file              */
  432.          token = strtok(buf,WHITESPACE);
  433.  
  434.          if (token == NULL)         /* Any data?                        */
  435.             continue;               /* No --> read another line         */
  436.  
  437.          if (token[0] == '#')
  438.             continue;                  /* Line is a comment; loop again */
  439.  
  440.          hostp = inithost(token);
  441.          token = strtok(NULL,WHITESPACE);
  442.  
  443.          if (hostp->hstatus == phantom)      /* Uninitilized?           */
  444.          {
  445.             if ((token != NULL) && equal(token,"="))
  446.             {
  447.                hostp->hstatus = aliasof;
  448.                token = strtok(NULL,WHITESPACE);
  449.             }
  450.             else if ((token != NULL) && equal(token,"|"))
  451.             {
  452.                hostp->hstatus = gatewayed;
  453.                token = strtok(NULL,"\n");
  454.                while(isspace( *token ))   /* Drop leading white space only */
  455.                   token++;
  456.                if (*token == '\0')        /* Empty string?           */
  457.                   token = NULL;           /* Yes --> Flag for error  */
  458.             }
  459.             else
  460.                hostp->hstatus = routed;  /* Flag as routing entry   */
  461.             if ( token == NULL )
  462.             {
  463.                printmsg(0,"loadhost: Missing path/alias name for host \"%s\"",
  464.                         hostp->hostname);
  465.                HostElements--;            /* Ignore the routing entry   */
  466.             }
  467.             else if (*token == '*')       /* Wildcard on right side?    */
  468.             {
  469.                printmsg(0,
  470.      "loadhost: Wildcard \"%s\" not allowed for real name of host \"%s\"",
  471.          token, hostp->hostname);
  472.                HostElements--;            /* Ignore the routing entry   */
  473.             }
  474.             else
  475.                hostp->via = strdup(token);
  476.          }
  477.          else
  478.             printmsg(0,"Entry \"%s\" in routing table is real host",
  479.                   hostp->hostname);
  480.       }  /* end while */
  481.  
  482.       fclose(ff);
  483.    }
  484.    else
  485.       printmsg(2,"loadhost: Cannot open host routing file %s",s_systems);
  486.  
  487.  
  488. /*--------------------------------------------------------------------*/
  489. /*                   Provide default for fromdomain                   */
  490. /*--------------------------------------------------------------------*/
  491.  
  492.    if (!hidden)               /* If no fromdomain provided ...       */
  493.       fdomain = domain;       /* Use domain as fromdomain            */
  494.  
  495.    hostp = inithost(fdomain);
  496.    if (hostp->hstatus == phantom)      /* Uninitilized?        */
  497.    {
  498.       hostp->hstatus = aliasof;
  499.       hostp->via = hidden ? mailserv : nodename;
  500.    }
  501.  
  502. /*--------------------------------------------------------------------*/
  503. /*    Shrink the table to whatever we actually need, then sort it     */
  504. /*--------------------------------------------------------------------*/
  505.  
  506.    hosts = realloc(hosts, HostElements *  sizeof(*hosts));
  507.    checkref(hosts);
  508.  
  509.    qsort(hosts, HostElements ,sizeof(hosts[0]) , hostcmp);
  510.  
  511. /*--------------------------------------------------------------------*/
  512. /*    If the user did not define a local domain, then generate one    */
  513. /*    based on our own domain name; the generated name will either    */
  514. /*    be of the format ".a.b.c" (incuding the trailing period) or     */
  515. /*    a null string.                                                  */
  516. /*--------------------------------------------------------------------*/
  517.  
  518.    if ( localdomain == NULL )
  519.    {
  520.       localdomain = strchr(domain,'.');
  521.       if (localdomain == NULL)
  522.          localdomain = "UUCP";
  523.       else
  524.          localdomain ++;      /* Step past the period                */
  525.       printmsg(2,"loadhost: local domain defined as \"%s\"",localdomain);
  526.    } /* if */
  527.    localdomainl = strlen(localdomain);
  528.  
  529. /*--------------------------------------------------------------------*/
  530. /*    Amend for the sin of typing the domain wrong in the sample      */
  531. /*    files for the old releases of UUPC/extended.                    */
  532. /*--------------------------------------------------------------------*/
  533.  
  534.    if (equal(localdomain,"UUPC"))
  535.    {
  536.       printmsg(0,"inithost: UUPC is an invalid domain name! \
  537. Change it to UUCP");
  538.       panic();
  539.    }
  540.  
  541. /*--------------------------------------------------------------------*/
  542. /*                      Display the final table                       */
  543. /*--------------------------------------------------------------------*/
  544.  
  545.    for (hit = 0; hit < HostElements; hit++)
  546.    {
  547.       printmsg(8,"loadhost: final entry %d is \"%s\" via \"%s\"",
  548.                   hit,
  549.                   hosts[hit].hostname,hosts[hit].via);
  550.    } /* for */
  551.  
  552. /*--------------------------------------------------------------------*/
  553. /*                          Return to caller                          */
  554. /*--------------------------------------------------------------------*/
  555.  
  556.    return (HostElements) ;
  557. } /*loadhost*/
  558.  
  559.  
  560. /*
  561.       h o s t c m p
  562.  
  563.       Accepts indirect pointers to two strings and compares
  564.       them using stricmp (case insensitive string compare)
  565.  */
  566.  
  567. int hostcmp( const void *a , const void *b )
  568. {
  569.    return stricmp(((struct HostTable*) a)->hostname,
  570.         ((struct HostTable*) b)->hostname);
  571. }  /*hostcmp*/
  572.